#pragma once

/**
 * TcpServer：对使用者对外提供的类
 */

#include "Acceptor.h"
#include "Callbacks.h"
#include "Connection.h"
#include "EventLoop.hpp"
#include "LoopThreadPool.h"

#include <unordered_map>

namespace devem {

class TcpServer {
private:
    EventLoop* CheckLoopNotNull(EventLoop* base_loop) {
        if (base_loop == nullptr) {
            LOG_FATAL("base_loop is nullptr!");
            abort();
        }
        return base_loop;
    }

    void NewConnCallback(int fd) {
        // pool 分配一个 subloop, 管理channel
        EventLoop* subloop = pool_.GetNextLoop();
        Connection* conn = new Connection(fd, subloop);

        // set callbacks
        conn->SetConnectionCallback(connected_callback_);
        conn->SetMessageCallback(message_callback_);
        conn->EstablishInLoop();
        conns_.insert(std::make_pair(fd, conn));
    }

    // 连接断开后的回调函数-----将该连接对应的 Connection 对象从 _connes 中移除
    void RemoveConnectionInLoop(const PtrConnection& con) {
        int fd = con->Fd();
        auto it = conns_.find(fd);
        if (it != conns_.end())
            conns_.erase(fd);
        return;
    }

    // 连接断开后的回调函数-----将该连接对应的 Connection 对象从 _connes 中移除
    void RemoveConnection(const PtrConnection& conn) {
        return base_loop_->RunInLoop(std::bind(&TcpServer::RemoveConnectionInLoop, this, conn));
    }

public:
    TcpServer() : acceptor_(base_loop_), pool_(base_loop_) {
        acceptor_.SetConnCallback(std::bind(&TcpServer::NewConnCallback, this, std::placeholders::_1));
    }

    void SetConnectedCallback(const ConnectedCallback& cb) { connected_callback_ = cb; }
    void SetMessageCallback(const MessageCallback& cb) { message_callback_ = cb; }
    void SetThreadNum(int num) { pool_.SetThreadNum(num); }

    void start() {
        pool_.start();
        base_loop_->start();
    }

private:
    Acceptor acceptor_;
    EventLoop* base_loop_;
    LoopThreadPool pool_;

    std::unordered_map<int, Connection*> conns_;
    // 由组件使用者传入
    ConnectedCallback connected_callback_;  // 有新连接时的回调
    MessageCallback message_callback_;      // 有读写消息时的回调
};

}  // namespace devem